//
//  GNRPeripheralManager.m
//  BlueToothDemo
//
//  Created by LvYuan on 2017/4/20.
//  Copyright © 2017年 UUPaotui. All rights reserved.
//

#import "GNRBLEPeripheralManager.h"
#import "NSString+Trims.h"
#import "GNRHelper.h"

@interface GNRBLEPeripheralManager ()<CBPeripheralManagerDelegate>

@property (nonatomic, strong)NSTimer * timer;
@property (nonatomic, assign)NSInteger serviceCount;
@property (nonatomic, strong)NSString * perName;

@property (nonatomic, copy)GNRBLEOpenPeripheralSucceeBlock openSucceeBlock;
@property (nonatomic, copy)GNRBLEOpenPeripheralErrorBlock openErrorBlock;
@property (nonatomic, copy)GNRBLEDidSubscribeBlock subBlock;
@property (nonatomic, copy)GNRBLEDidUnsubscribeBlock unsubBlock;
@property (nonatomic, copy)GNRBLERevProfileInfoBlock revProfileInfoBlock;

@property (nonatomic, strong)GNRCentral * central;//当前想要链接的central
@end

@implementation GNRBLEPeripheralManager

+ (instancetype)manager{
    static GNRBLEPeripheralManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[self alloc] init];
    });
    return manager;
}

- (BOOL)removeCen:(GNRCentral *)central{
    for (GNRCentral * cen in self.centrals) {
        if ([central.name isEqualToString:cen.name]) {
            [self.centrals removeObject:cen];
            return YES;
        }
    }
    return NO;
}

- (NSMutableArray<GNRCentral *> *)centrals{
    if (!_centrals) {
        _centrals = [NSMutableArray array];
    }
    return _centrals;
}

//初始化外设管理者
- (void)setup{
    _peripheralManger = [[CBPeripheralManager alloc]initWithDelegate:self queue:nil options:@{@"identification":[_profileInfo objectForKey:@"identification"]}];
}

//初始化服务
- (void)setUpServices{
    //删除之前的
    [self.peripheralManger removeAllServices];
    _peripheralManger.delegate = self;
    /*
        心跳服务 特征
     */
    CBUUID * characteristicRateUUID = [CBUUID UUIDWithString:UUID_Characteristic_Notify_Time];
    CBMutableCharacteristic * rateCharacteristic = [[CBMutableCharacteristic alloc]initWithType:characteristicRateUUID properties:CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable];
    
    CBUUID * serviceRateUUID = [CBUUID UUIDWithString:UUID_Service_Notify_HeartRate];
    CBMutableService * service1 = [[CBMutableService alloc]initWithType:serviceRateUUID primary:YES];
    [service1 setCharacteristics:@[rateCharacteristic]];
    
    /*
        用户信息服务 特征
     */
    CBUUID * charaUserNameReadUUID = [CBUUID UUIDWithString:UUID_Characteristic_UserInfo];
    NSData * data = [[self profileInfoDesc] dataUsingEncoding:NSUTF8StringEncoding];
    CBMutableCharacteristic *readCharacteristic = [[CBMutableCharacteristic alloc]initWithType:charaUserNameReadUUID properties:CBCharacteristicPropertyRead value:data permissions:CBAttributePermissionsReadable];

    CBUUID * charaGetUserNameReadUUID = [CBUUID UUIDWithString:UUID_Characteristic_GetUserInfo];
    CBMutableCharacteristic *writeCharacteristic = [[CBMutableCharacteristic alloc]initWithType:charaGetUserNameReadUUID properties:CBCharacteristicPropertyWrite value:nil permissions:CBAttributePermissionsWriteable];
    
    CBUUID * serviceProfileInfoUUID = [CBUUID UUIDWithString:UUID_Service_Read_ProfileInfo];
    CBMutableService * service2 = [[CBMutableService alloc]initWithType:serviceProfileInfoUUID primary:YES];
    
    [service2 setCharacteristics:@[readCharacteristic,writeCharacteristic]];
    
    [self.peripheralManger addService:service1];
    [self.peripheralManger addService:service2];
}

//获取用户信息字典有 就传json 没有 就传name
- (NSString *)profileInfoDesc{
    if (_profileInfo.allKeys.count) {
        NSString * json = [GNRHelper dictionaryToJson:_profileInfo];
//        GLog(@"json %@",json);
        return json;
    }
    return self.name;
}

- (NSString *)perName{
    NSString * name = NamePrefix_Peripheral;
    NSString * nickName = _name;
    if (nickName.length) {
        return [NSString stringWithFormat:@"%@%@_%@",name,nickName,_identification];
    }
    return name;
}


- (void)stopAdvertising{
    [self.peripheralManger stopAdvertising];
}

//开始广播
- (void)startAdvertising{
    _peripheralManger.delegate = self;
    //广播两个服务 并设置 设备名
    CBUUID * serviceProfileInfoUUID = [CBUUID UUIDWithString:UUID_Service_Read_ProfileInfo];
    CBUUID * serviceNotifyUUID = [CBUUID UUIDWithString:UUID_Service_Notify_HeartRate];

    [self.peripheralManger startAdvertising:@{
                                             CBAdvertisementDataServiceUUIDsKey:@[serviceProfileInfoUUID,serviceNotifyUUID],
                                             CBAdvertisementDataLocalNameKey : self.perName,
                                             }];
}

//开启设备回调
- (void)openPeripheralSuccee:(GNRBLEOpenPeripheralSucceeBlock)succeeBlock error:(GNRBLEOpenPeripheralErrorBlock)errorBlock{
    NSAssert(_name.length, @"请设置name！");
    NSAssert(_identification.length, @"请设置identification！");
    
    _openSucceeBlock = nil;
    _openSucceeBlock = [succeeBlock copy];
    _openErrorBlock = nil;
    _openErrorBlock = [errorBlock copy];

    [self setup];

}

#pragma mark - 状态改变回调
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral{
    NSString * domain = nil;
    switch (peripheral.state) {
        case CBCentralManagerStateUnknown:
            domain = @"CBCentralManagerStateUnknown";
            break;
        case CBCentralManagerStateResetting:
            domain = @"CBCentralManagerStateResetting";
            break;
        case CBCentralManagerStateUnsupported:
            domain = @"CBCentralManagerStateResetting";
            break;
        case CBCentralManagerStateUnauthorized:
            domain = @"CBCentralManagerStateUnauthorized";
            break;
        case CBCentralManagerStatePoweredOff:
            domain = @"CBCentralManagerStatePoweredOff";
            break;
        case CBCentralManagerStatePoweredOn:
            [self setUpServices];//开始配置服务
            break;
        default:
            break;
    }
    
    if (domain) {
        NSError * error = [NSError errorWithDomain:domain code:peripheral.state userInfo:nil];
        if (_openErrorBlock) {
            _openErrorBlock(error);
        }
    }
}

#pragma mark - 添加了服务回调
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error{
    if (error==nil) {
        _serviceCount++;
    }
    if (_serviceCount==2) {
        //添加两个服务后才开始广播
        if (_openSucceeBlock) {
            _openSucceeBlock(peripheral);
        }
    }
    NSLog(@"didAddService");
}

#pragma mark - 已经开始广播
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error{
    if (error) {
        NSLog(@"error %@",error.localizedDescription);
    }else{
        
    }
    NSLog(@"advertisiong");
}

//被订阅的回调
- (void)revProfileInfoBlock:(GNRBLERevProfileInfoBlock)revProfileInfoBlock
          didSubscribeBlock:(GNRBLEDidSubscribeBlock)subscribeBlock{
    _subBlock = nil;
    _subBlock = [subscribeBlock copy];
    _revProfileInfoBlock = nil;
    _revProfileInfoBlock = [revProfileInfoBlock copy];
}

//被取消订阅的回调
- (void)didUnsubscribeBlock:(GNRBLEDidUnsubscribeBlock)unsubscribeBlock{
    _unsubBlock = nil;
    _unsubBlock = [unsubscribeBlock copy];
}

//创建一个新的
- (GNRCentral *)newCentral{
    GNRCentral * cen = [GNRCentral new];
    return cen;
}

//是否存在
- (GNRCentral *)isExsit:(CBCentral *)central{
    for (GNRCentral * cen in self.centrals) {
        if ([cen.identifier isEqualToString:central.identifier.UUIDString]) {
            return cen;
        }
    }
    return nil;
}

#pragma mark - 对central的操作的响应
//订阅
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic{
    _central.central = central;
    _central.notifyChara = characteristic;
    [self.centrals addObject:_central];
    if (_subBlock) {
        _subBlock(_central,characteristic);
    }
}

//开始发送通知
- (void)startSendForCentral:(GNRCentral *)central{
    central.connected = YES;
    _central = central;
    if (_timer==nil) {//开启定时器
        _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(sendDataTimer:) userInfo:nil  repeats:YES];
    }
}

//拒绝订阅请求
- (BOOL)refuseSubscribeForCentral:(GNRCentral *)central{
    _central = nil;
    NSData * value = [Refuse_Notify_Name dataUsingEncoding:NSUTF8StringEncoding];
    return [self updateValue:value central:central];
}

//发送数据，发送当前时间的秒数
- (void)sendDataTimer:(NSTimer *)t{
    for (GNRCentral * central in self.centrals) {
        if (central.connected) {
            //执行回应Central通知数据
            id  time = [@([[NSDate date] timeIntervalSince1970]).stringValue dataUsingEncoding:NSUTF8StringEncoding];
            [self updateValue:time central:central];
        }
    }
}

- (BOOL)updateValue:(id)date central:(GNRCentral *)central{
    if (central.notifyChara) {
        return  [self.peripheralManger updateValue:date forCharacteristic:(CBMutableCharacteristic *)central.notifyChara onSubscribedCentrals:nil];
    }
    return NO;
}

//停止发送
- (void)stopSendNotify:(GNRCentral *)central{
    central.connected = NO;
}

//取消了定阅
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic{
    GNRCentral * cen = [self isExsit:central];
    [self stopSendNotify:cen];//取消了订阅
    if (_unsubBlock&&cen) {
        _unsubBlock(cen,characteristic);
    }
}

//读取请求
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request{
    NSLog(@"didReceiveReadRequest");
    if (request.characteristic.properties & CBCharacteristicPropertyRead) {//是否有权限读取数据
        NSData * data = request.characteristic.value;
        [request setValue:data];
        //对请求做出成功响应
        [peripheral respondToRequest:request withResult:CBATTErrorSuccess];
    }else{
        //没有读取权限的响应
        [peripheral respondToRequest:request withResult:CBATTErrorReadNotPermitted];
    }
}

- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests{
    NSLog(@"didReceiveWriteRequests");
    CBATTRequest * request = requests[0];
    if (request.characteristic.properties & CBCharacteristicPropertyWrite) {//有写入的权限
        CBMutableCharacteristic * c = (CBMutableCharacteristic *)request.characteristic;
        c.value = request.value;
        NSString * json = [[NSString alloc] initWithData:c.value encoding:NSUTF8StringEncoding];
        id result = [GNRHelper objWithJsonString:json];
        GNRCentral * cen = [self newCentral];
        _central = cen;
        [cen.profileInfo setValuesForKeysWithDictionary:result];
        cen.name = [NSString stringWithFormat:@"%@%@_%@",NamePrefix_Peripheral,cen.profileInfo.nickname,cen.profileInfo.identification];
        if (cen&&result) {
            if (_revProfileInfoBlock) {
                _revProfileInfoBlock(cen,result);
            }
        }
        [peripheral respondToRequest:request withResult:CBATTErrorSuccess];
    }else{
        [peripheral respondToRequest:request withResult:CBATTErrorWriteNotPermitted];//没有写权限
    }
}

@end
